/*
 * Rectangle.cc
 *
 *  Created on: Feb 26, 2011
 *      Author: topcoder
 */

#include "Rectangle.h"
#include "Decimal.h"
#include "math.h"
#include "float.h"

const float  MIN_SIDE_LENGTH = 0; 
const float  MAX_SIDE_LENGTH = 100;
const double INVALID_AREA = 0;
const double INVALID_PERIMETER = 0;
const unsigned CUT_DECIMAL_PLACE = 2;
const float INVALID_LENGTH = 0;
const float INVALID_WIDTH = 0;

#define ASSERT_GREATER(value1,value2) ((value1-value2) > FLT_EPSILON)
#define ASSERT_LESS(value1,value2) ((value2-value1) > FLT_EPSILON)
#define GET_RESULT_BY_FLAG(flag, value1, value2) (flag?value1:value2)

static bool isValid(const float value)
{
    return (ASSERT_GREATER(value,MIN_SIDE_LENGTH)) && (ASSERT_LESS(value,MAX_SIDE_LENGTH));
}

Rectangle::Rectangle(const float len, const float width):len_m(len),width_m(width)
{
}

double Rectangle::getArea() const
{
    return GET_RESULT_BY_FLAG(isValidRectangle(),\
               Decimal::processFloatPrecision(len_m*width_m,true,CUT_DECIMAL_PLACE),\
               INVALID_AREA);
}

double Rectangle::getPerimeter() const
{
    return GET_RESULT_BY_FLAG(isValidRectangle(),2*(len_m + width_m),INVALID_PERIMETER);
}

void Rectangle::setLength(const float len)
{
    if(isValid(len))
    {
        len_m = Decimal::processFloatPrecision(len,false,CUT_DECIMAL_PLACE);
    }
}

void Rectangle::setWidth(const float width)
{
    if(isValid(width))
    {
        width_m = Decimal::processFloatPrecision(width,false,CUT_DECIMAL_PLACE);
    }

}

bool Rectangle::isValidRectangle() const
{
    return (isValid(len_m) && isValid(width_m));
}


